import 'package:flutter/material.dart';

class QsIndicator extends Decoration {
  final TabController? tabController;
  final double indicatorBottom; // 调整指示器下边距
  final double indicatorWidth; // 指示器宽度
  final double indicatorHeight; // 指示器高度
  final BorderSide borderSide;

  const QsIndicator(
      {this.borderSide = const BorderSide(width: 2.0, color: Colors.white),
      this.tabController,
      this.indicatorBottom = 0.0,
      this.indicatorWidth = 4,
      this.indicatorHeight = 4});

  const QsIndicator.none(
      {this.borderSide =
          const BorderSide(width: 0.0, color: Colors.transparent),
      this.tabController,
      this.indicatorBottom = 0.0,
      this.indicatorWidth = 4,
      this.indicatorHeight = 4});

  @override
  BoxPainter createBoxPainter([VoidCallback? onChanged]) {
    return _UnderlinePainter(
      this,
      onChanged,
      tabController?.animation,
      indicatorWidth,
      indicatorHeight,
    );
  }

  Rect _indicatorRectFor(Rect indicator, TextDirection textDirection) {
    /// 自定义固定宽度
    double w = indicatorWidth;
    //中间坐标
    double centerWidth = (indicator.left + indicator.right) / 2;
    return Rect.fromLTWH(
      //距离左边距
      tabController?.animation == null ? centerWidth - w / 2 : centerWidth - 1,
      // 距离上边距
      indicator.bottom - borderSide.width - indicatorBottom,
      w,
      borderSide.width,
    );
  }

  @override
  Path getClipPath(Rect rect, TextDirection textDirection) {
    return Path()..addRect(_indicatorRectFor(rect, textDirection));
  }
}

class _UnderlinePainter extends BoxPainter {
  Animation<double>? animation;
  double indicatorWidth;
  double indicatorHeight;

  _UnderlinePainter(this.decoration, VoidCallback? onChanged, this.animation,
      this.indicatorWidth, this.indicatorHeight)
      : super(onChanged);

  final QsIndicator decoration;

  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    assert(configuration.size != null);
    // 以offset坐标为左上角 size为宽高的矩形
    final Rect rect = offset & configuration.size!;
    final TextDirection textDirection = configuration.textDirection!;
    // 返回tab矩形
    final Rect indicator = decoration._indicatorRectFor(rect, textDirection)
      ..deflate(decoration.borderSide.width / 2.0);
    // 圆角画笔
    final Paint paint = decoration.borderSide.toPaint()
      ..style = PaintingStyle.fill
      ..strokeCap = StrokeCap.round;
    if (animation != null) {
      num x = animation!.value; // 变化速度 0-0.5-1-1.5-2...
      num d = x - x.truncate(); // 获取这个数字的小数部分
      num? y;
      if (d < 0.5) {
        y = 2 * d;
      } else if (d > 0.5) {
        y = 1 - 2 * (d - 0.5);
      } else {
        y = 1;
      }
      canvas.drawRRect(
          RRect.fromRectXY(
              Rect.fromCenter(
                  center: indicator.centerLeft,
                  width: indicatorWidth * 6 * y + indicatorWidth,
                  height: indicatorHeight),
              2,
              2),
          paint);
    } else {
      canvas.drawLine(indicator.bottomLeft, indicator.bottomRight, paint);
    }
  }
}

class RectangleIndicator extends Decoration {
  const RectangleIndicator({
    this.borderSide = const BorderSide(width: 0, color: Colors.white),
    this.insets = EdgeInsets.zero,
    this.radius = 4.0,
    this.padding = const EdgeInsets.all(2.0),
    this.rectangleColor = Colors.redAccent,
    this.shadowColor,
  });

  final BorderSide borderSide;
  final EdgeInsetsGeometry insets;
  final double radius;
  final EdgeInsets padding;
  final Color rectangleColor;
  final Color? shadowColor;

  @override
  Decoration? lerpFrom(Decoration? a, double t) {
    if (a is UnderlineTabIndicator) {
      return UnderlineTabIndicator(
        borderSide: BorderSide.lerp(a.borderSide, borderSide, t),
        insets: EdgeInsetsGeometry.lerp(a.insets, insets, t)!,
      );
    }
    return super.lerpFrom(a, t);
  }

  @override
  Decoration? lerpTo(Decoration? b, double t) {
    if (b is UnderlineTabIndicator) {
      return UnderlineTabIndicator(
        borderSide: BorderSide.lerp(borderSide, b.borderSide, t),
        insets: EdgeInsetsGeometry.lerp(insets, b.insets, t)!,
      );
    }
    return super.lerpTo(b, t);
  }

  @override
  BoxPainter createBoxPainter([VoidCallback? onChanged]) {
    return _CirclePainter(this, onChanged);
  }

  Rect _indicatorRectFor(Rect rect, TextDirection textDirection) {
    assert(rect != null);
    assert(textDirection != null);
    final Rect indicator = insets.resolve(textDirection).deflateRect(rect);
    return Rect.fromLTWH(
      indicator.left + padding.left,
      padding.top,
      indicator.width - padding.left - padding.right,
      indicator.height - padding.top - padding.bottom,
    );
  }

  @override
  Path getClipPath(Rect rect, TextDirection textDirection) {
    return Path()..addRect(_indicatorRectFor(rect, textDirection));
  }
}

class _CirclePainter extends BoxPainter {
  _CirclePainter(this.decoration, VoidCallback? onChanged) : super(onChanged);

  final RectangleIndicator decoration;

  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    assert(configuration.size != null);
    final Rect rect = offset & configuration.size!;
    final TextDirection textDirection = configuration.textDirection!;
    // 计算 indicator 的 rect
    final Rect indicator = decoration
        ._indicatorRectFor(rect, textDirection)
        .deflate(decoration.borderSide.width / 2.0);
    // 定义绘制的样式
    final RRect rrect =
        RRect.fromRectAndRadius(indicator, Radius.circular(decoration.radius));
    final Paint paint = decoration.borderSide.toPaint()
      ..style = PaintingStyle.fill
      ..color = decoration.rectangleColor;
    final Path path = Path()..addRRect(rrect.shift(Offset(1, 1)));
    // 绘制阴影
    if (decoration.shadowColor != null) {
      canvas.drawShadow(path, decoration.shadowColor!, 4, false);
    }
    // 绘制圆角矩形
    canvas.drawRRect(rrect, paint);
  }
}
